
import { arrayAdd, arrayRemove } from '@datorama/akita';
import { catchError, firstValueFrom, from, switchMap, tap } from 'rxjs';

import messageService from '@/services/messageService';
import { MessageItem } from '@/models/Message';
import { CMD } from '@/constants/message';
import { CustomMessage, CustomMsgParam, LinkRequest, TuwenText } from '@/models/request/msgReq';
import ChannelStyle from '@@/channel/channelStyle'

import { MessageQuery, MessageStore, makeStore as makeMsgStore } from "@/state/message/store";
import { AuthQuery, makeStore as makeAuthStore } from '@/state/auth/store';
import { RoomQuery, makeStore as makeRoomStore } from '@/state/room/store';
import { TimHandler, makeHandler } from '@/utils/timHandler';

export class MessageFacade {
  constructor(private store: MessageStore, private query: MessageQuery, private authQuery: AuthQuery, private roomQuery: RoomQuery, private timHandler: TimHandler) {
    //箭头函数不需要bind作用域
    // this.loginIM = this.loginIM.bind(this);
  }

  readonly isLoading$ = this.query.isLoading$;
  readonly isSDKReady$ = this.query.isSDKReady$;
  readonly groupId$ = this.query.groupId$;
  readonly enterMsg$ = this.query.enterMsg$;
  readonly notifyMsg$ = this.query.notifyMsg$;
  readonly msgList$ = this.query.msgList$;
  readonly tuwenMsgList$ = this.query.tuwenMsgList$;
  // readonly notifyMsg$ = this.timHandler.notifyMsg.asObservable();

  //绑定监听。加群或登录IM之前都必须先绑定监听
  bindOn = () => {
    this.timHandler.bindOn();
  }

  //根据IM登录状态进行预登陆
  loginIM = () => {
    //设置loading状态避免重复请求，因为登陆组件不是单例，多实例状态下会重复触发请求
    this.store.setLoading(true);

    return messageService.getUserSigSvc(this.authQuery.userId)
      .pipe(
        switchMap(userSign => from(this.timHandler.initTimSDK(this.authQuery.userId, userSign))),
        //登陆完成设置loading状态false
        tap(() => this.store.setLoading(false)),
        //异常也重置laoding状态false
        catchError(() => {
          this.store.setLoading(false);
          throw new Error("请求出错");
        })
      )
  }

  //滑动往上拉取历史消息时调用
  getPagingMsgs = () => {
    this.timHandler.getPagingMsgs(this.query.groupId);
  }

  //发送群文本消息
  sendRoomTextMsg = (msg: string) => {
    return this.timHandler.sendRoomTextMsg(this.roomQuery.roomId, msg);
  }

  //发送群图片消息
  sendRoomImageMsg = () => {
    return this.timHandler.sendRoomImageMsg(this.roomQuery.roomId);
  }

  //发送群音频消息
  sendRoomAudioMsg = (cancelRecord: boolean) => {
    return this.timHandler.startRoomAudioMsg(this.roomQuery.roomId, cancelRecord);
  }

  //结束录制群音频消息
  endRoomAudioMsg = () => {
    return this.timHandler.sendRoomAudioMsg();
  }

  //发送群视频消息
  sendRoomVideoMsg = () => {
    return this.timHandler.sendRoomVideoMsg(this.roomQuery.roomId);
  }

  //发送群自定义消息
  sendRoomCustomMsg = (data: TuwenText) => {
    const msg = {} as CustomMessage;
    msg.data = JSON.stringify(data);
    return this.timHandler.sendRoomCustomMsg(this.roomQuery.roomId, msg);
  }

  //发送C2C自定义消息
  sendC2cCustomMsg = (userId: string, param: CustomMsgParam) => {
    const msg = {} as CustomMessage;
    msg.data = JSON.stringify(param);

    return this.timHandler.sendC2cCustomMsg(userId, msg);
  }

  //发送群消息，不传muteTime则为解除禁言
  muteGroupMember = (groupId: string, userId: string, muteTime?: number) => {
    this.timHandler.muteGroupMember(groupId, userId, muteTime);
  }

  //TODO 踢出房间成员，需要结合黑名单使用
  kickMember = (userId: string) => {
    firstValueFrom(messageService.sendC2cMsgSvc(userId, CMD.KICK_MEMBER))
  }

  // 连麦的发起，接受，拒绝相关C2C消息通知
  sendLinkMsg = (userId: string, cmd: string) => {
    const fromUserReq = {} as LinkRequest;
    fromUserReq.from = this.authQuery.userId;
    fromUserReq.to = userId;
    fromUserReq.fromAvatar = this.authQuery.userInfo.avatarUrl;
    fromUserReq.fromNick = this.authQuery.userInfo.nickName;
    fromUserReq.timestamp = new Date().getTime() / 1000;

    const msg = {} as CustomMsgParam;
    msg.cmd = cmd;
    msg.data = fromUserReq;

    return this.sendC2cCustomMsg(userId, msg)
  }

  //撤回消息（2分钟内可以撤回）
  revokeMessage = (msg: MessageItem) => {

    //FIXME: 音视频聊天室的消息不支持撤回，暂不启用
    this.timHandler.revokeMessage(msg);
  }

  applyJoinBigGroup = async (groupId: string) => {
    await this.timHandler.applyJoinBigGroup(groupId);
    // if (this.authQuery.loginStatus && this.query.isSDKReady) {
    //   await this.timHandler.getRoomMsgs(groupId);
    // }
    this.insertTips(groupId, this.roomQuery.tips || `欢迎来到${ChannelStyle.appName}LIVE,请不要发布色情、违法、低俗、侵权等法律禁止的內容信息,健康参与。`);
  }

  updateMyProfile = (nick: string, avatar: string) => {
    return this.timHandler.updateMyProfile(nick, avatar);
  }

  //插入系统通知到聊天区域
  insertTips = (groupId: string, tips: string) => {
    const time = new Date().getTime() / 1000;

    const thisTips = {
      from: "administrator",
      to: groupId,
      nick: "管理员",
      avatar: "https://leconglive-wxapp-1301839528.file.myqcloud.com/wxIcon/logo1.png",
      sequence: time / 1000,
      random: time,
      priority: "normal",
      type: "text",
      time,
      payload: { text: tips }
    }

    const msgListRef = this.query.msgList;
    //数组最后一条消息
    const lastMsg = msgListRef[msgListRef.length - 1];

    //不重新发上面的通知
    if (!lastMsg || (lastMsg.to === groupId && lastMsg.payload.text !== tips)) {
      this.store.update(({ msgList }) => ({
        msgList: arrayAdd(msgList, thisTips)
      }))
    } else {
      return;
    }
  }

  //离开群组
  quitBigGroup = () => {
    this.timHandler.quitBigGroup(this.query.groupId);
  }

  //重置群组数据
  resetMsgStore = (roomId?: string) => {
    this.timHandler.resetGroup(roomId);
  }

  //由群主发起修改其他成员的角色，AVChatRoom无效
  changeImRole = (roomId: string, userId: string, role?: string) => {
    this.timHandler.setGroupMemberRole(roomId, userId, role);
  }

  getMemberInfo = (roomId: string, userIds: string[]) => {
    return this.timHandler.getMemberInfo(roomId, userIds);
  }

  //在本地删除被撤回的图文消息
  revokeTuwenMsg = (sequence: number) => {
    this.store.update(({ tuwenMsgList }) => ({
      tuwenMsgList: arrayRemove(tuwenMsgList, item => item.sequence === sequence)
    }));
  }

  //FIXME: 废弃 翻页获取回来的数据直接替换当前tuwenMsgList
  // getTuwenMsgs = (roomId: string, page: number, size: number, sequence?: number) => {
  //   return messageService.getTuwenMsgSvc(roomId, page, size, sequence)
  //     .pipe(
  //       map(list => list.data),
  //       tap(twList => {
  //         if (this.roomQuery.status === ROOM_STATUS.ENDED) {
  //           //直接替换更新当前图文数组
  //           this.store.update(state => {
  //             state.tuwenMsgList = twList;
  //           })
  //         } else {
  //           //往后面翻页,看旧记录
  //           this.store.update(({ tuwenMsgList }) => ({
  //             tuwenMsgList: arrayAdd(tuwenMsgList, twList)
  //           }));
  //         }
  //       })
  //     )
  // }

  //清理操作，以免页面进入房间时重复触发handleGroupSystemNotify通知操作
  clearNotifyMsg = () => {
    this.store.update(state => {
      state.notifyMsg = {};
    });
  }
}

export const makeFacade = (): MessageFacade => {
  const [store, query] = makeMsgStore();
  const [, authQuery] = makeAuthStore();
  const [, roomQuery] = makeRoomStore();

  const handler = makeHandler(store, query, authQuery);

  return new MessageFacade(store, query, authQuery, roomQuery, handler);
}